﻿using Microsoft.EntityFrameworkCore;
using YDT_SeckillService.Domain.Entities;

namespace YDT_SeckillService.Infrastructure.Data
{
    public class SeckillServiceDbContext : DbContext
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public SeckillServiceDbContext(DbContextOptions<SeckillServiceDbContext> options) : base(options) { }

        /// <summary>秒杀活动表</summary>
        public DbSet<Seckill> Seckills { get; set; }
        /// <summary>秒杀商品表</summary>
        public DbSet<SeckillProduct> SeckillProducts { get; set; }

        /// <summary>
        /// 配置模型 - 定义数据库表结构和关系
        /// </summary>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // 配置秒杀活动实体
            modelBuilder.Entity<Seckill>(entity =>
            {
                // 主键配置
                entity.HasKey(e => e.Id);

                // 属性配置
                entity.Property(e => e.TimeTitleUrl)
                    .IsRequired()
                    .HasMaxLength(500); // 时间主题URL最大长度500

                entity.Property(e => e.SeckillDate)
                    .IsRequired()
                    .HasColumnType("date"); // 使用date类型存储日期

                entity.Property(e => e.SeckillStartTime)
                    .IsRequired()
                    .HasColumnType("time"); // 使用time类型存储时间

                entity.Property(e => e.SeckillEndTime)
                    .IsRequired()
                    .HasColumnType("time"); // 使用time类型存储时间

                entity.Property(e => e.TimeStatus)
                    .HasConversion<string>() // 枚举转换为字符串存储
                    .HasMaxLength(20);

                // 索引配置
                entity.HasIndex(e => e.SeckillDate); // 秒杀日期索引
                entity.HasIndex(e => e.TimeStatus); // 状态索引

                // 导航属性配置
                entity.HasMany(e => e.SeckillProducts)
                      .WithOne()
                      .HasForeignKey("TimeId") // 外键
                      .OnDelete(DeleteBehavior.Cascade); // 级联删除
            });

            // 配置秒杀商品实体
            modelBuilder.Entity<SeckillProduct>(entity =>
            {
                // 主键配置
                entity.HasKey(e => e.Id);

                // 属性配置
                entity.Property(e => e.SeckillName)
                    .IsRequired()
                    .HasMaxLength(200); // 秒杀名称最大长度200

                entity.Property(e => e.SeckillUrl)
                    .HasMaxLength(500); // 秒杀URL最大长度500

                entity.Property(e => e.SeckillPrice)
                    .HasColumnType("decimal(18,2)"); // 秒杀价格使用decimal(18,2)

                entity.Property(e => e.SeckillPercent)
                    .HasMaxLength(10); // 秒杀百分比最大长度10

                entity.Property(e => e.SeckillDescription)
                    .HasMaxLength(1000); // 秒杀描述最大长度1000

                entity.Property(e => e.SeckillType)
                    .HasConversion<string>() // 枚举转换为字符串存储
                    .HasMaxLength(20);

                entity.Property(e => e.SeckillStatus)
                    .HasConversion<string>() // 枚举转换为字符串存储
                    .HasMaxLength(20);

                // 索引配置
                entity.HasIndex(e => e.TimeId); // 秒杀时间ID索引
                entity.HasIndex(e => e.ProductId); // 商品ID索引
                entity.HasIndex(e => e.SeckillIsTop); // 置顶索引
                entity.HasIndex(e => e.SeckillStatus); // 状态索引
            });
        }

        /// <summary>
        /// 保存更改 - 自动设置更新时间
        /// </summary>
        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        {
            // 自动设置更新时间
            var entries = ChangeTracker.Entries()
                .Where(e => (e.Entity is Seckill || e.Entity is SeckillProduct) &&
                           (e.State == EntityState.Modified || e.State == EntityState.Added));

            foreach (var entityEntry in entries)
            {
                if (entityEntry.Entity is Seckill seckill)
                {
                    seckill.UpdateTime = DateTime.UtcNow;
                }
                else if (entityEntry.Entity is SeckillProduct seckillProduct)
                {
                    seckillProduct.UpdateTime = DateTime.UtcNow;
                }
            }

            return await base.SaveChangesAsync(cancellationToken);
        }
    }
}
